TerraformのクラウドコントロールAPI専用のproviderを使ってみた
2021年9月30日にクラウドコントロールAPIがGA(一般提供開始)しました。
従来、各サービスごとにバラバラだったAPIの使い方を、一貫した方法で使えるようにしたAPIです。またAWSサービスのみならず CloudFormation Registry で利用可能なサードパーティー製ソリューションもこのAPIを通して利用可能です。
前回、このクラウドコントロールAPIをTerraformのaws provider経由で使ってみました。
今回はTerraform経由でのもう一つの使い方をご紹介します。クラウドコントロールAPI専用のprovider「awscc」がリリースされていますのでこれを使ってみます。
なおこのproviderは現在tech previewです。本番環境での利用はまだ控えておきましょう。
使ってみた
前回と同様、このproviderを使って2AZにそれぞれPublicとPrivateサブネットを持つような一般的なVPC構成を作ってみたいと思います。
Terraformとproviderの定義
terraform { required_version = "1.0.10" required_providers { awscc = { source = "hashicorp/awscc" version = "0.4.0" } } } provider "awscc" { region = "ap-northeast-1" }
普通のproviderの設定ですね。
認証
認証はaws providerと同様、多様な方法で可能です。アクセスキー・シークレットキーを providerブロックのattributeで渡す、環境変数にセットする、profile attributeを使う、AWS_PROFILE環境変数を使うなど。 AWS SSO Profileも使えました。
まずはVPCだけ
こんな感じのコードです。
resource "awscc_ec2_vpc" "vpc" { cidr_block = "192.168.0.0/16" enable_dns_support = true enable_dns_hostnames = true instance_tenancy = "default" tags = [{ key = "Name" value = "basic-vpc" }] }
前回試したaws providerでクラウドコントロールAPIを使う例では、どんなリソースを作る場合でもaws_cloudcontrolapi_resource
を使い、そのtype_name
値を切り替えることでプロビジョニングするリソースを切り替えていました。が、この awscc providerはリソースごとにResourceが定義されています。
resource "aws_cloudcontrolapi_resource" "vpc" { type_name = "AWS::EC2::VPC" desired_state = jsonencode({ CidrBlock = "192.168.0.0/16" EnableDnsSupport = true EnableDnsHostnames = true InstanceTenancy = "default" Tags = [{ Key = "Name" Value = "plain-vpc" }] }) }
resource "aws_cloudcontrolapi_resource" "vpc" { type_name = "AWS::EC2::VPC" desired_state = jsonencode(yamldecode( <<-EOT CidrBlock: "192.168.0.0/16" EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: "plain-vpc" EOT )) }
aws_cloudcontrolapi_resource
はリソースのプロパティを desired_state
attribute以下にJSON型で押し込む形になっています。そのためjsonencode()
などを挟まないと書きにくいです。この点awsccはより簡潔に書けて良いと思います。
以下はaws providerのaws_vpc
リソースを使った、つまり一般的なTerraformでのVPCの書き方ですが、ほとんど前述のawsccのコードと同じですよね。
resource "aws_vpc" "vpc" { cidr_block = "192.168.0.0/16" enable_dns_support = true enable_dns_hostnames = true instance_tenancy = "default" tags = { Name = "plain-vpc" } }
他のリソースも
全体のコードは以下のようになりました。前回aws providerのaws_cloudcontrolapi_resource
でやったときと同様、一部リソースがクラウドコントロールAPIでは未対応だったのでその部分はaws providerを使っています。
terraform { required_version = "1.0.10" required_providers { awscc = { source = "hashicorp/awscc" version = "0.4.0" } aws = { source = "hashicorp/aws" version = "3.63.0" } } } provider "awscc" { region = "ap-northeast-1" } provider "aws" { region = "ap-northeast-1" } resource "awscc_ec2_vpc" "vpc" { cidr_block = "192.168.0.0/16" enable_dns_support = true enable_dns_hostnames = true instance_tenancy = "default" tags = [{ key = "Name" value = "basic-vpc" }] } # public subnet resource "aws_internet_gateway" "igw" { vpc_id = awscc_ec2_vpc.vpc.id tags = { Name = "basic-vpc-igw" } } data "aws_availability_zones" "az" {} resource "aws_subnet" "public" { count = 2 vpc_id = awscc_ec2_vpc.vpc.id cidr_block = cidrsubnet(awscc_ec2_vpc.vpc.cidr_block, 8, count.index) availability_zone = data.aws_availability_zones.az.names[count.index] map_public_ip_on_launch = true tags = { Name = "basic-vpc-public-subnet-${count.index + 1}" } } resource "awscc_ec2_route_table" "public" { vpc_id = awscc_ec2_vpc.vpc.id tags = [{ key = "Name" value = "basic-vpc-public-subnet-rtb" }] } resource "aws_route" "public" { route_table_id = awscc_ec2_route_table.public.id gateway_id = aws_internet_gateway.igw.id destination_cidr_block = "0.0.0.0/0" } resource "awscc_ec2_subnet_route_table_association" "public" { count = 2 route_table_id = awscc_ec2_route_table.public.id subnet_id = aws_subnet.public.*.id[count.index] } # private subnet resource "aws_subnet" "private" { count = 2 vpc_id = awscc_ec2_vpc.vpc.id cidr_block = cidrsubnet(awscc_ec2_vpc.vpc.cidr_block, 8, count.index + 2) availability_zone = data.aws_availability_zones.az.names[count.index] map_public_ip_on_launch = false tags = { Name = "basic-vpc-private-subnet-${count.index + 1}" } } resource "awscc_ec2_route_table" "private" { vpc_id = awscc_ec2_vpc.vpc.id tags = [{ key = "Name" value = "basic-vpc-private-subnet-rtb" }] } resource "awscc_ec2_subnet_route_table_association" "private" { count = 2 route_table_id = awscc_ec2_route_table.private.id subnet_id = aws_subnet.private.*.id[count.index] }
使ってみた感想
先に書いたとおり、aws providerのaws_cloudcontrolapi_resource
よりは書きやすい、読みやすいと思います。が、クラウドコントロールAPIの一番のユースケースは、aws providerで未対応のリソースをプロビジョニングしたいとき、です。この観点で言うとaws_cloudcontrolapi_resource
に軍配が上がるかなと思います。aws_cloudcontrolapi_resource
は該当リソースがクラウドコントロールAPIに対応してさえいればすぐ使うことができます。対してこのawscc providerはproviderのバージョンアップで対応リソースが増えない限りは使うことができません。どんどん対応リソースは増えているようですが…
将来的に、awsccでプロビジョニングできるリソースの種類がaws providerと同じくらいになったら、awsccが覇権を握る未来が来るかもしれません。